package org.rc.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.rc.dto.*;
import org.rc.entity.*;
import org.rc.service.MenuService;
import org.rc.service.RoleMenuService;
import org.rc.service.RoleService;
import org.rc.service.UserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/role")
public class RoleController {

    @Autowired
    RoleService roleService;

    @Autowired
    RoleMenuService roleMenuService;

    @Autowired
    MenuService menuService;

    @Autowired
    UserRoleService userRoleService;

    @PutMapping("")
    public Res addRole(@RequestBody RoleAddDto roleAddDto){
        if(StringUtils.isEmpty(roleAddDto.getRoleName())){
            return Res.failure("请输入角色名称");
        }
        if(!CollectionUtils.isEmpty(roleService.getByRoleName(roleAddDto.getRoleName()))){
            return Res.failure("角色名称重复，请重新输入");
        }
        roleService.add(roleAddDto);
        return Res.success();
    }

    @PostMapping("")
    public Res updateRole(@RequestBody RoleUpdateDto roleUpdateDto){
        if(StringUtils.isEmpty(roleUpdateDto.getRoleName())){
            return Res.failure("请输入用户名");
        }
        if(!CollectionUtils.isEmpty(roleService.getByRoleName(roleUpdateDto.getRoleName(),roleUpdateDto.getId()))){
            return Res.failure("角色名称重复，请重新输入");
        }
        roleService.updateRole(roleUpdateDto);
        return Res.success();
    }

    @GetMapping("/no_admin_dcz")
    public Res getAllRolesExcludeAdminAndDcz(){
        return Res.success(roleService.getRolesNotInAdminAndDcz());
    }

    @PostMapping("/page")
    public Res getUserPage(@RequestBody RolePageDto rolePageDto){
        Page<Role> rolePage = roleService.getRolePage(rolePageDto);
        List<Role> roles = rolePage.getRecords();
        List<RolePageRes> rolePageResList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(roles)){
            Map<Long,List<RoleMenu>> roleMenuMap =null;
            Map<Integer,Menu> menuMap = null;
            List<RoleMenu> roleMenus = roleMenuService.getByRoleIds(rolePage.getRecords().stream().map(Role :: getId).collect(Collectors.toList()));
            if(!CollectionUtils.isEmpty(roleMenus)){
                roleMenuMap= roleMenus.stream().collect(Collectors.groupingBy(RoleMenu :: getRoleId));
                List<Menu> menus = menuService.getMenusByIds(roleMenus.stream().map(RoleMenu :: getMenuId).collect(Collectors.toList())).stream()
                        .filter(menu -> menu.getPId().equals(0)).sorted(Comparator.comparing(Menu :: getName)).collect(Collectors.toList());
                menuMap =  menus.stream().collect(Collectors.toMap(Menu :: getId,menu->menu));
            }
            for(Role role : roles){
                RolePageRes rolePageRes = new RolePageRes();
                rolePageRes.setId(role.getId());
                rolePageRes.setName(role.getName());
                List<String> menuNames = new ArrayList<>();
                if(!CollectionUtils.isEmpty(roleMenuMap)){
                    List<RoleMenu> roleMenuList = roleMenuMap.get(role.getId());
                    if(!CollectionUtils.isEmpty(roleMenuList)){
                        for(RoleMenu roleMenu : roleMenuList){
                            if(menuMap.containsKey(roleMenu.getMenuId())){
                                menuNames.add(menuMap.get(roleMenu.getMenuId()).getName());
                            }
                        }
                    }
                }
                rolePageRes.setMenus(menuNames);
                rolePageResList.add(rolePageRes);
            }
        }
        PageDto pageDto = PageDto.of(rolePage);
        pageDto.setData(rolePageResList);
        return Res.success(pageDto);
    }

    @GetMapping("/{id}")
    public Res getMenusByRoleId(@PathVariable(value = "id") Long id){
        List<MenuDto> menus = new ArrayList<>();
        List<RoleMenu> roleMenus = roleMenuService.getByRoleId(id);
        if(!CollectionUtils.isEmpty(roleMenus)){
            menus = menuService.getMenuDtoByIds(roleMenus.stream().map(RoleMenu :: getMenuId).collect(Collectors.toList()));
        }
        return Res.success(menus);
    }

    @GetMapping("/menus/{id}")
    public Res getSelectedMenusByRoleId(@PathVariable(value = "id") Long id){
        List<Menu> menus = menuService.getMenuList();
        List<RoleMenu> roleMenus = roleMenuService.getByRoleId(id);
        Map<Integer,RoleMenu> roleMenuMap = roleMenus.stream().collect(Collectors.toMap(RoleMenu :: getMenuId,roleMenu->roleMenu));
        List<MenuSelectedDto> menuSelectedDtos = menus.stream().map(menu -> {
            MenuSelectedDto menuSelectedDto = MenuSelectedDto.getInstance(menu);
            if(!CollectionUtils.isEmpty(roleMenus) && roleMenuMap.containsKey(menu.getId())){
                menuSelectedDto.setSelected(true);
            }
            return menuSelectedDto;
        }).collect(Collectors.toList());
        return Res.success(makePidTree(menuSelectedDtos,0));
    }
    private List<MenuSelectedDto> makePidTree(List<MenuSelectedDto> menuDtos, Integer pId){
        List<MenuSelectedDto> children = menuDtos.stream().filter(x->x.getPId().equals(pId)).sorted(Comparator.comparing(MenuSelectedDto :: getWeight)).collect(Collectors.toList());
        List<MenuSelectedDto> successor = menuDtos.stream().filter(x->!x.getPId().equals(pId)).collect(Collectors.toList());
        children.forEach(x -> x.setChildren(makePidTree(successor,x.getId())));
        return children;
    }

    @DeleteMapping("/{id}")
    public Res deleteRole(@PathVariable(value = "id") Long id){
        if(null == id){
            return Res.failure("请选择需要删除的角色");
        }
        if(!CollectionUtils.isEmpty(userRoleService.selectByRoleId(id))){
            return Res.failure("所选角色下存在绑定账号，请先解绑后再删除。");
        }
        //删除角色
        roleService.deleteRole(id);
        //删除角色菜单
        roleMenuService.deleteByRoleId(id);
        return Res.success();
    }

    @DeleteMapping("")
    public Res deleteRoles(@RequestBody RolesDeleteDto rolesDeleteDto){
        if(CollectionUtils.isEmpty(rolesDeleteDto.getIds())){
            return Res.failure("请选择需要删除的角色");
        }
        if(!CollectionUtils.isEmpty(userRoleService.selectByRoleIds(rolesDeleteDto.getIds()))){
            return Res.failure("所选角色下存在绑定账号，请先解绑后再删除。");
        }
        roleService.deleteRoles(rolesDeleteDto.getIds());
        roleMenuService.deleteByRoleIds(rolesDeleteDto.getIds());
        return Res.success();
    }

}
